module Piston
  module ViewModelBase
    module ClassMethods
      def declare_event( *events )
        events.each do |event|
          define_handler_methods( event )
        end
      end

      def define_handler_methods( event )
        event_name = event.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
        class_eval <<-EOS
        include System::ComponentModel::INotifyPropertyChanged

        def handlers( event_name )
          @event_handlers ||= Hash.new
          @event_handlers[ event_name ] ||= []
        end

        def add_#{event_name}( handler )
          handlers( :#{event_name} ) << handler
        end

        def remove_#{event_name}( handler )
          handlers( :#{event_name} ).delete handler
        end

        def #{event_name}( sender, args )
          handlers( :#{event_name} ).each do |handler|
            handler.invoke sender, args
          end
        end

        def Raise#{event_name}(property_name)
          self.#{event_name}(self,
            System::ComponentModel::#{event_name}EventArgs.new(property_name))
        end
        EOS
      end
    end

    def self.included(receiver)
      receiver.extend ClassMethods
    end
  end
end